﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lesson20
{
    class Person
    {
        public string name;
        public int Age { get; set; }
        public string Address { get; set; }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            // 特殊语法
            #region var隐式类型
            // var是一种特殊的变量类型
            // 它可以用来表示任意类型的变量
            // 注意：1、var不能作为类的成员，只能用于临时变量声明，一般写在函数语句块中
            // 2、var 必须初始化

            var i = 5;
            var str = "hello";
            var arr = new int[] { 1, 2, 3, 4, 5 };
            var list = new List<int> { 1, 2, 3, 4, 5 };
            #endregion

            #region 设置对象初始值
            // 声明对象时，可以通过直接写大括号的形式初始化 公共成员 变量和属性
            Person p = new Person() { name = "nm", Age = 18, Address = "505" };
            Person p2 = new Person() { Age = 20 };
            // 如果是有参构造，大括号的用法是一样的
            #endregion

            #region 设置集合初始值
            // 声明集合时，可以通过直接写大括号的形式直接初始化内部属性
            int[] arr2 = new int[] { 1, 2, 3, 4, 5 };
            List<int> list2 = new List<int> { 1, 2, 3, 4, 5 };
            List<Person> listP = new List<Person>
            {
                new Person() { name = "nm", Age = 18, Address = "505" },
                new Person() { name = "nm2", Age = 20, Address = "303" }
            };

            Dictionary<int, string> dic = new Dictionary<int, string>
            {
                //{键， 值}
                { 1, "one" },
                { 2, "two" },
                { 3, "three" }
            };
            #endregion

            #region 匿名类型
            // var变量可以声明为自定义的匿名类型，声明时直接用new关键字加上大括号，声明完成后是只读的，只能有成员
            var anonymous = new { Name = "匿名", Age = 18, height = 180 };
            Console.WriteLine(anonymous.Name);
            #endregion

            #region 可空类型
            // Nullable 可空类型
            // 1、值类型是不能赋值为 空的
            //int c = null; // 报错
            // 2、声明时 在值类型后面加上？号，表示这个值类型可以赋值为 空
            int? c = null; // 不报错
            // 3、判断是否为空  HasValue
            if (c.HasValue)
            {
                Console.WriteLine(c);
                Console.WriteLine(c.Value);
            }
            else
            {
                Console.WriteLine("c为空");
            }
            // 4、安全获取可空类型的值
            //    如果为空， 默认返回 值类型的默认值
            Console.WriteLine(c.GetValueOrDefault());
            //    也可以指定一个默认值
            Console.WriteLine(c.GetValueOrDefault(100));
            Console.WriteLine(c);

            // 值类型
            float? f = null;
            double? d = null;

            object obj = null;
            if(obj != null)
            {
                obj.ToString();
            }
            // 这样 使用 ?.相当于一种语法糖，能够自动取判断obj是否为空，如果是空，就不会执行ToString()，也不会报错
            obj?.ToString();
            Console.WriteLine(obj?.ToString());

            int[] arrInt = null;
            //Console.WriteLine(arrInt[0]); // 这样运行时会报错
            Console.WriteLine(arrInt?[0]);

            //委托
            Action action = null;
            if(action != null)
            {
                action();
            }
            action?.Invoke(); // 快捷简写

            #endregion

            #region 空合并操作符
            // 空合并操作符 ??
            // 左边值 ?? 右边值
            // 如果左边值不为空，返回左边值，否则返回右边值
            // 只要是可以为null的类型都能用

            // 三目运算符的简化版

            int? a = null;
            int b = a == null ? 100 : a.Value;  // 要用 .Value 获取值，不然 ?之后不能确定值类型，会报错
            int b2 = a ?? 100; 

            string str2 = null;
            str2 = str2 ?? "hello";

            #endregion

            #region 内插字符串
            // 关键符号 $          // 类似于python中的f-string |  js中的模板字符串
            // 用$符号来构造字符串，让字符串中可以拼接变量

            string name = "cat";
            Console.WriteLine($"你的名字是{name}");


            #endregion

            #region 单句逻辑简略写法
            // 当逻辑语句只有一句时，可以省略大括号
            //if (true)
            //    Console.WriteLine("hello");
            //for (int count = 0; count < 10; count++)
            //    Console.WriteLine(count);
            //while (true)
            //    Console.WriteLine("hello");

            // 函数中、lambda表达式只要一句时也可以省略

            #endregion

        }
    }
}
